/*
 * Copyright 2005-2013 biz-united. All rights reserved.
 * Support: http://www.biz-united.com.cn
 * License: http://www.biz-united.com.cn/?page_id=5&act=3
 */
package net.biz.service.impl;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.*;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import com.home766.util.DateTime;
import net.biz.entity.*;
import net.biz.service.*;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import net.biz.Page;
import net.biz.Pageable;
import net.biz.ResourceNotFoundException;
import net.biz.Template;
import net.biz.dao.ArticleDao;
import net.biz.dao.BrandDao;
import net.biz.dao.ProductDao;
import net.biz.dao.PromotionDao;
import net.biz.util.FreemarkerUtils;
import net.biz.util.ParamsUtil;
import net.biz.util.ParamsUtil;

import com.home766.service.SchemeService;

/**
 * Service - 静态化
 *
 * @author BIZ Team
 * @version 3.0
 */
@Service("staticServiceImpl")
public class StaticServiceImpl implements StaticService, ServletContextAware {

    /**
     * Sitemap最大地址数
     */
    private static final Integer SITEMAP_MAX_SIZE = 40000;


    private static final Long AD_SCROLL_POSITION = 3L;

    /**
     * servletContext
     */
    private ServletContext servletContext;

    @Resource(name = "freeMarkerConfigurer")
    private FreeMarkerConfigurer freeMarkerConfigurer;
    @Resource(name = "templateServiceImpl")
    private TemplateService templateService;
    @Resource(name = "articleDaoImpl")
    private ArticleDao articleDao;
    @Resource(name = "productDaoImpl")
    private ProductDao productDao;
    @Resource(name = "brandDaoImpl")
    private BrandDao brandDao;
    @Resource(name = "promotionDaoImpl")
    private PromotionDao promotionDao;

    @Resource(name = "tagServiceImpl")
    private TagService tagService;
    @Resource(name = "productServiceImpl")
    private ProductService productService;
    @Resource(name = "productCategoryServiceImpl")
    private ProductCategoryService productCategoryService;
    @Resource(name = "schemeServiceImpl")
    private SchemeService schemeService;

    @Resource(name = "adPositionServiceImpl")
    private AdPositionService adPositionService;

//	@Autowired
//	private IDictionaryValueService dictionaryValueService;
//	@Autowired
//	private IDictionaryTypeService dictionaryTypeService;

    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    @Transactional(readOnly = true)
    public int build(String templatePath, String staticPath, Map<String, Object> model) {
        Assert.hasText(templatePath);
        Assert.hasText(staticPath);

        FileOutputStream fileOutputStream = null;
        OutputStreamWriter outputStreamWriter = null;
        Writer writer = null;
        try {
            freemarker.template.Template template = freeMarkerConfigurer.getConfiguration().getTemplate(templatePath);
            File staticFile = new File(servletContext.getRealPath(staticPath));
            File staticDirectory = staticFile.getParentFile();
            if (!staticDirectory.exists()) {
                staticDirectory.mkdirs();
            }
            fileOutputStream = new FileOutputStream(staticFile);
            outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
            writer = new BufferedWriter(outputStreamWriter);
            template.process(model, writer);
            writer.flush();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(writer);
            IOUtils.closeQuietly(outputStreamWriter);
            IOUtils.closeQuietly(fileOutputStream);
        }
        return 0;
    }

    @Transactional(readOnly = true)
    public int build(String templatePath, String staticPath) {
        return build(templatePath, staticPath, null);
    }

    @Transactional(readOnly = true)
    public int buildIndex(String templatePath, String staticPath) {
        Map<String, Object> model = new HashMap<String, Object>();
        Pageable pageable = new Pageable(1, 5);
   /* ProductCategory warmCategory = productCategoryService.find(new Long(79));
    ProductCategory acCategory = productCategoryService.find(new Long(82));
    ProductCategory waterCategory = productCategoryService.find(new Long(84));
    ProductCategory seimCategory = productCategoryService.find(new Long(171));
    ProductCategory windCategory = productCategoryService.find(new Long(145));

    model.put("pageWarm", productService.findPage(warmCategory, null, null, null, null, null, null, true, true, null, false, null, null, null, pageable));
    model.put("pageAC", productService.findPage(acCategory, null, null, null, null, null, null, true, true, null, false, null, null, null, pageable));
    model.put("pageWater", productService.findPage(waterCategory, null, null, null, null, null, null, true, true, null, false, null, null, null, pageable));
    model.put("pageSeim", productService.findPage(seimCategory, null, null, null, null, null, null, true, true, null, false, null, null, null, pageable));
    model.put("pageWind", productService.findPage(windCategory, null, null, null, null, null, null, true, true, null, false, null, null, null, pageable));
*/
        //特惠商品
        List<Tag> tags = new ArrayList<Tag>();
        Tag tag = tagService.find(ParamsUtil.PRODUCT_TEHUI_ACTIVITY);
        Page<Product> pageGoods = new Page<Product>();
        Page<Product> pageSet = new Page<Product>();
        Set<Ad> adSet = new TreeSet<>(new BeanComparator("order"));
        if (tag != null) {
            tags.add(tag);
            ProductCategory goodsCategory = productCategoryService.find(null);
            pageGoods = productService.findPage(goodsCategory, null, null, tags, null, null, null, true, true, null, false, null, null, null, pageable);
            ProductCategory setCategory = productCategoryService.find(new Long(170)); //套餐
            pageSet = productService.findPage(setCategory, null, null, tags, null, null, null, true, true, null, false, null, null, null, pageable);
            AdPosition adPosition = adPositionService.find(AD_SCROLL_POSITION);
            if(adPosition!=null){
                adSet = adPosition.getAds();
            }
        }
        Set<Ad> ads = new TreeSet<>(new BeanComparator("order"));
        long curTime = System.currentTimeMillis() ;
        for (Ad ad:adSet) {
            if(null!=ad.getBeginDate()&&null!=ad.getEndDate()){
                long beginTime = ad.getBeginDate().getTime();
                long endTime = ad.getEndDate().getTime();
                if(beginTime<curTime && curTime<endTime){
                    ads.add(ad);
                }
            }else {
                ads.add(ad);
            }
        }
        model.put("adSet", ads);
        model.put("pageGoods", pageGoods);
        model.put("pageSet", pageSet);
        model.put("pageScheme", schemeService.findPage(pageable, null, null, null, null, null, null, true, true));//方案

    
 /*   //导航栏二级菜单
        //智能暖气
    ProductCategory pageWarm_productCategory = productCategoryService.find(new Long(139));
	model.put("pageWarm_productCategory", pageWarm_productCategory);
	   //智能空调
    ProductCategory pageAC_productCategory = productCategoryService.find(new Long(86));
	model.put("pageAC_productCategory", pageAC_productCategory);
	  //智能净水
	ProductCategory pageWater_productCategory = productCategoryService.find(new Long(135));
	model.put("pageWater_productCategory", pageWater_productCategory);
	  //智能家电
	ProductCategory pageSeim_productCategory = productCategoryService.find(new Long(173));
	model.put("pageSeim_productCategory", pageSeim_productCategory);
	  //智能新风
	ProductCategory pageWind_productCategory = productCategoryService.find(new Long(145));
	model.put("pageWind_productCategory", pageWind_productCategory);
	*/
        return build(templatePath, staticPath, model);
    }


    @Transactional(readOnly = true)
    public int build(Article article) {
        Assert.notNull(article);

        delete(article);
        Template template = templateService.get(ParamsUtil.ARTICLECONTENT);
//		Template template_app = templateService.get(ParamsUtil.ARTICLECONTENT_APP);
        int buildCount = 0;
        if (article.getIsPublication()) {
            Map<String, Object> model = new HashMap<String, Object>();
            model.put("article", article);
            for (int pageNumber = 1; pageNumber <= article.getTotalPages(); pageNumber++) {
                article.setPageNumber(pageNumber);
                buildCount += build(template.getTemplatePath(), article.getPath(), model);
//				buildCount += build(template_app.getTemplatePath(), article.getPath(), model);
            }
            article.setPageNumber(null);
        }
        return buildCount;
    }

    @Transactional(readOnly = true)
    public int build(Product product) {
        Assert.notNull(product);

        delete(product);
        Template template = templateService.get(ParamsUtil.PRODUCTCONTENT);
//		Template template_app = templateService.get(ParamsUtil.PRODUCTCONTENT_APP);
        int buildCount = 0;
        if (product.getIsMarketable()) {
            Map<String, Object> model = new HashMap<String, Object>();
            model.put("product", product);
            buildCount += build(template.getTemplatePath(), product.getPath(), model);
//			buildCount += build(template_app.getTemplatePath(), product.getPathApp(), model);
        }
        return buildCount;
    }

    @Transactional(readOnly = true)
    public int buildIndex() {
        int buildCount = 0;
        Template template = templateService.get(ParamsUtil.INDEX);
//		Template template_app = templateService.get(ParamsUtil.INDEX_APP);
//		buildCount+=build(template_app.getTemplatePath(), template_app.getStaticPath());
        buildCount += buildIndex(template.getTemplatePath(), template.getStaticPath());    //
        return buildCount;
    }

    @Transactional(readOnly = true)
    public int buildSitemap() {
        int buildCount = 0;
        Template sitemapIndexTemplate = templateService.get(ParamsUtil.SITEMAPINDEX);
        Template sitemapTemplate = templateService.get(ParamsUtil.SITEMAP);
//		Template sitemapIndexTemplate_app = templateService.get(ParamsUtil.SITEMAPINDEX_APP);
//		Template sitemapTemplate_app = templateService.get(ParamsUtil.SITEMAP_APP);
        Map<String, Object> model = new HashMap<String, Object>();
        List<String> staticPaths = new ArrayList<String>();
        for (int step = 0, index = 0, first = 0, count = SITEMAP_MAX_SIZE; ; ) {
            try {
                model.put("index", index);
                String templatePath = sitemapTemplate.getTemplatePath();
                String staticPath = FreemarkerUtils.process(sitemapTemplate.getStaticPath(), model);

//				String templatePath_app = sitemapTemplate_app.getTemplatePath();
//				String staticPath_app = FreemarkerUtils.process(sitemapTemplate_app.getStaticPath(), model);
                if (step == 0) {
                    List<Article> articles = articleDao.findList(first, count, null, null);
                    model.put("articles", articles);
                    if (articles.size() < count) {
                        step++;
                        first = 0;
                        count -= articles.size();
                    } else {
                        buildCount += build(templatePath, staticPath, model);
//						buildCount += build(templatePath_app, staticPath_app, model);
                        articleDao.clear();
                        articleDao.flush();
                        staticPaths.add(staticPath);
//						staticPaths.add(staticPath_app);
                        model.clear();
                        index++;
                        first += articles.size();
                        count = SITEMAP_MAX_SIZE;
                    }
                } else if (step == 1) {
                    List<Product> products = productDao.findList(first, count, null, null);
                    model.put("products", products);
                    if (products.size() < count) {
                        step++;
                        first = 0;
                        count -= products.size();
                    } else {
                        buildCount += build(templatePath, staticPath, model);
//						buildCount += build(templatePath_app, staticPath_app, model);
                        productDao.clear();
                        productDao.flush();
                        staticPaths.add(staticPath);
//						staticPaths.add(staticPath_app);
                        model.clear();
                        index++;
                        first += products.size();
                        count = SITEMAP_MAX_SIZE;
                    }
                } else if (step == 2) {
                    List<Brand> brands = brandDao.findList(first, count, null, null);
                    model.put("brands", brands);
                    if (brands.size() < count) {
                        step++;
                        first = 0;
                        count -= brands.size();
                    } else {
                        buildCount += build(templatePath, staticPath, model);
//						buildCount += build(templatePath_app, staticPath_app, model);
                        brandDao.clear();
                        brandDao.flush();
                        staticPaths.add(staticPath);
//						staticPaths.add(staticPath_app);
                        model.clear();
                        index++;
                        first += brands.size();
                        count = SITEMAP_MAX_SIZE;
                    }
                } else if (step == 3) {
                    List<Promotion> promotions = promotionDao.findList(first, count, null, null);
                    model.put("promotions", promotions);
                    buildCount += build(templatePath, staticPath, model);
//					buildCount += build(templatePath_app, staticPath_app, model);
                    promotionDao.clear();
                    promotionDao.flush();
                    staticPaths.add(staticPath);
//					staticPaths.add(staticPath_app);
                    if (promotions.size() < count) {
                        model.put("staticPaths", staticPaths);
                        buildCount += build(sitemapIndexTemplate.getTemplatePath(), sitemapIndexTemplate.getStaticPath(), model);
//						buildCount += build(sitemapIndexTemplate_app.getTemplatePath(), sitemapIndexTemplate_app.getStaticPath(), model);
                        break;
                    } else {
                        model.clear();
                        index++;
                        first += promotions.size();
                        count = SITEMAP_MAX_SIZE;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return buildCount;
    }

    @Transactional(readOnly = true)
    public int buildOther() {
        int buildCount = 0;
        Template shopCommonJsTemplate = templateService.get(ParamsUtil.SHOPCOMMONJS);

        Template adminCommonJsTemplate = templateService.get(ParamsUtil.ADMINCOMMONJS);

        Template padCommonJsTemplate = templateService.get(ParamsUtil.SHOPCOMMONJS_PAD);

        buildCount += build(shopCommonJsTemplate.getTemplatePath(), shopCommonJsTemplate.getStaticPath());

        buildCount += build(adminCommonJsTemplate.getTemplatePath(), adminCommonJsTemplate.getStaticPath());

        buildCount += build(padCommonJsTemplate.getTemplatePath(), padCommonJsTemplate.getStaticPath());

        return buildCount;
    }

    //	/**
//	 * 生成静态字典js
//	 * @param buildCount
//	 * @return
//	 */
//	@Transactional(readOnly = true)
//	public int buildDictionary(int buildCount){
//		List<DictionaryType> types= dictionaryTypeService.searchAllTypeNo(true);
//		List<DictionaryValue> values=dictionaryValueService.searchSystemDictionaryValue();
//		Map<String, Object> result=new HashMap<String, Object>();
//		List<Map<String, Object>> resultListType=new ArrayList<Map<String, Object>>();
//		if(null!=types&&!types.isEmpty()){
//			for(DictionaryType dt:types){
//				Map<String, Object> tempType=new HashMap<String,Object>();
//				tempType.put("typeNo", dt.getTypeNo());
//				tempType.put("title", dt.getTitle());
//				if(null!=values&&!values.isEmpty()){
//					List<Map<String, Object>> resultListValue=new ArrayList<Map<String, Object>>();
//					for(DictionaryValue dv:values){
//						if(dt.getTypeNo()==dv.getTypeNo()){
//							Map<String, Object> tempValue=new HashMap<String,Object>();
//							tempValue.put("code", dv.getCode());
//							tempValue.put("title", dv.getTitle());
//							resultListValue.add(tempValue);
//						}
//					}
//					tempType.put("values", resultListValue);
//				}
//				resultListType.add(tempType);
//			}
//		}
//		String str=JsonUtils.toJson(resultListType);
//		
//		result.put("coboTypes", str);
//		Template pubnlicCommonJsTemplate = templateService.get(ParamsUtil.PUBLIC_DICTIONARY_JS);
//		buildCount += build(pubnlicCommonJsTemplate.getTemplatePath(), pubnlicCommonJsTemplate.getStaticPath(),result);
//		return buildCount;
//	}
    @Transactional(readOnly = true)
    public int buildAll() {
        int buildCount = 0;
        for (int i = 0; i < articleDao.count(); i += 20) {
            List<Article> articles = articleDao.findList(i, 20, null, null);
            for (Article article : articles) {
                buildCount += build(article);
            }
            articleDao.clear();
        }
        for (int i = 0; i < productDao.count(); i += 20) {
            List<Product> products = productDao.findList(i, 20, null, null);
            for (Product product : products) {
                buildCount += build(product);
            }
            productDao.clear();
        }
        buildIndex();
        buildSitemap();
        buildOther();
        return buildCount;
    }

    @Transactional(readOnly = true)
    public int delete(String staticPath) {
        Assert.hasText(staticPath);

        File staticFile = new File(servletContext.getRealPath(staticPath));
        if (staticFile.exists()) {
            staticFile.delete();
            return 1;
        }
        return 0;
    }

    @Transactional(readOnly = true)
    public int delete(Article article) {
        Assert.notNull(article);

        int deleteCount = 0;
        for (int pageNumber = 1; pageNumber <= article.getTotalPages() + 1000; pageNumber++) {
            article.setPageNumber(pageNumber);
            int count = delete(article.getPath());
            if (count < 1) {
                break;
            }
            deleteCount += count;
        }
        article.setPageNumber(null);
        return deleteCount;
    }

    @Transactional(readOnly = true)
    public int delete(Product product) {
        Assert.notNull(product);

        return delete(product.getPath());
    }

    @Transactional(readOnly = true)
    public int deleteIndex() {
        int deleteCount = 0;
        Template template = templateService.get(ParamsUtil.INDEX);
//		Template template_app = templateService.get(ParamsUtil.INDEX_APP);
//		deleteCount+=delete(template_app.getStaticPath());
        deleteCount += delete(template.getStaticPath());
        return deleteCount;
    }

    @Transactional(readOnly = true)
    public int deleteOther() {
        int deleteCount = 0;
        Template shopCommonJsTemplate = templateService.get(ParamsUtil.SHOPCOMMONJS);
        Template adminCommonJsTemplate = templateService.get(ParamsUtil.ADMINCOMMONJS);
        Template publicDictionaryJsTemplate = templateService.get(ParamsUtil.PUBLIC_DICTIONARY_JS);
//		Template shopCommonJsTemplate_app = templateService.get(ParamsUtil.SHOPCOMMONJS_APP);
//		Template adminCommonJsTemplate_app = templateService.get(ParamsUtil.ADMINCOMMONJS_APP);
        deleteCount += delete(shopCommonJsTemplate.getStaticPath());
//		deleteCount += delete(shopCommonJsTemplate_app.getStaticPath());
        deleteCount += delete(adminCommonJsTemplate.getStaticPath());
        deleteCount += delete(publicDictionaryJsTemplate.getStaticPath());
//		deleteCount += delete(adminCommonJsTemplate_app.getStaticPath());
        return deleteCount;
    }


}

